﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Web;
using Tools.Api.Http;

namespace Tools {

    public class HttpAdapter : IHttper {
        /// <summary>
        /// 因为HttpContext本身不能mock。
        /// HttpContextBase的实现类，用来真正的替换HttpContext。
        /// 方便进行单元测试
        /// </summary>
        private HttpContextWrapper HttpContext { get; set; }
        private HttpRequestBase Request { get; set; }

        public HttpAdapter(HttpContext httpContext) {
            HttpContext = new HttpContextWrapper(httpContext);
            Request = HttpContext.Request;
        }

        public HttpAdapter(HttpContextBase httpContext) {
            HttpContext = (HttpContextWrapper)httpContext;
            Request = httpContext.Request;
        }

        public void SetResponseCookie(string ticketKeyName, IDictionary<string, string> dictionary, string domian) {
            var ticketCookie = new HttpCookie(ticketKeyName);
            //TODO:Cookie过期时间ticketCookie.Expires = DateTimeOffset.UtcNow.AddDays(5);
            foreach (var item in dictionary) {
                ticketCookie.Values.Add(item.Key, item.Value);
                ticketCookie.Domain = domian;
            }
            HttpContext.Response.Cookies.Set(ticketCookie);
        }

        public IDictionary<string, string> GetRequestCookie(string ticketKeyName) {
            HttpCookie ticketCookie = HttpContext.Request.Cookies[ticketKeyName];
            var dictionary = new Dictionary<string, string>();
            if (ticketCookie == null) return dictionary;

            foreach (string key in ticketCookie.Values.Keys) {
                dictionary[key] = ticketCookie.Values[key];
            }
            return dictionary;
        }

        /// <summary>
        /// 将cookie设为过期，交由浏览器处理
        /// </summary>
        /// <param name="ticketKeyName"></param>
        /// <param name="domain">清除的时候楚需要有Domain，传递的并没有传递Domain？可能是出于安全考虑</param>
        public void RmoveCookie(string ticketKeyName, string domain) {
            HttpCookie ticketCookie = HttpContext.Request.Cookies[ticketKeyName];
            if (ticketCookie != null) {
                ticketCookie.Expires = DateTime.Now.AddDays(-1);
                ticketCookie.Domain = domain;
                HttpContext.Response.Cookies.Set(ticketCookie);
            }
        }

        /// <summary>
        /// 不接受来自 自己的请求
        /// TODO：IP6
        /// </summary>
        /// <returns>null:没有来源URL</returns>
        public string RequestHost() {
            var url = HttpContext.Request.UrlReferrer;
            if (url != null) {
                var authority = url.Authority;
                //var safeHost = url.DnsSafeHost; 
                //var hots = url.Host;
                return authority;
            }
            return null;
        }

        public IDictionary<string, object> GetNormalRequestDict() {
            return new SortedDictionary<string, object>
                {
                    {"Ip", GetIp()},
                    {"Browser", GetBrowserVersion()},
                    {"VisitPath", GetVisitUrl()},
                    {"PostParams", GetPostParams()},
                    {"HttpMethod", GetHttpMethod()},
                    {"Platform", GetPlatform()},
                    {"PreferredRendering", GetPreferredRendering()},
                    {"UserAgent", GetUserAgent()}
                };
        }

        public string GetIp() {
            string ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            if (string.IsNullOrEmpty(ip)) {
                ip = Request.ServerVariables["REMOTE_ADDR"];
            }

            return ip;
        }

        public string GetBrowserVersion() {
            return String.Format("{0}-{1}", Request.Browser.Type, Request.Browser.Version);
        }

        public NameValueCollection GetPostParams() {
            //const string str = "{0}:{1}&";
            //return request.Form.Keys.Cast<string>().Aggregate(str, (current, key) => String.Format(current, key, request.Form[key]) + str);
            return Request.Form;
        }

        public NameValueCollection GetHeaders() {
            return Request.Headers;
        }

        public void SetHeader(string name, string val) {
            Request.Headers[name] = val;
        }

        public string GetHttpMethod() {
            return Request.HttpMethod;
        }

        public string GetVisitUrl() {
            return String.Format("{0}", Request.Url);
        }

        public string GetPreferredRendering() {
            return String.Format("<Type:{0}-Mime:{1}>", Request.Browser.PreferredRenderingType, Request.Browser.PreferredRenderingMime);

        }

        public string GetPlatform() {
            return Request.Browser.Platform;
        }

        public string GetUserAgent() {
            return Request.UserAgent;
        }

        public void Remove(string key) {
            HttpContext.Session.Remove(key);
        }

        public void Store(string key, object data) {
            HttpContext.Session[key] = data;
        }

        public T Retrieve<T>(string key) {
            try {
                T itemStored = (T)HttpContext.Session[key];
                if (itemStored == null) {
                    itemStored = default(T);
                }
                return itemStored;
            }
            catch (Exception ex) {
                Debug.WriteLine(ex.StackTrace);
                return default(T);
            }
        }

        public T Pull<T>(string key, Func<T> method) {
            throw new NotImplementedException();
        }
    }
}